
// glcheck allows developer to check the hardware capabilities of all GPU's
// returning an array of records reflecting the attached hardware. This
// list can be regenerated on Display Manager notifications to keep the
// client update to on capabilities and setup changes.  This is provided as
// sample to allow developers the freedom to check as few or as many
// conditions and capabilities as they would like or add their own checks

#include <Carbon/Carbon.h>

#include <ApplicationServices/ApplicationServices.h>

typedef struct {
  // developers can add capabilities as required
  
  CGDirectDisplayID cgDisplayID; // CG display ID (main identifier)
  unsigned long displayID; // QD display ID
  GDHandle hGDevice; // graphics device handle
  CGOpenGLDisplayMask cglDisplayMask; // CGL display mask
  
  // current (at time of look up) device geometry
  long deviceWidth; // pixel width
  long deviceHeight; // pixel width
  long deviceOriginX; // left location of device (relative to main device)
  long deviceOriginY; // upper location of device (relative to main device)
  short deviceDepth; // pixel depth in bits
  short deviceRefresh; // integer refresh rate in Hz
  
  // Renderer info
  long deviceVRAM; // video memory in bytes
  long deviceTextureRAM; // uses current mode (geometry, pixel depth, etc.)
  unsigned long rendererID; // renderer ID
  char strRendererName [256]; // name of hardware renderer
  char strRendererVendor [256]; // name of hardware renderer vendor
  char strRendererVersion [256]; // string rep of hardware renderer version
  bool fullScreenCapable; // does device support full screen
  // can add more device specs as you want
  
  // Renderer Caps
  long textureUnits; // standard gl path max number of texture units
  long maxTextureSize; // maximum 1D and 2D texture size supported
  long max3DTextureSize; // maximum 3D texture size supported
  long maxCubeMapTextureSize; // maximum cube map texture size supported
  long maxRectTextureSize; // maximum rectangular texture size supported
  
  // OpenGL version support
  unsigned short glVersion; // bcd gl version (ie. 1.4 is 0x0140)
  
  
  // Functionality
  bool fSpecularVector; // GL_APPLE_specular_vector
  bool fTransformHint; // GL_APPLE_transform_hint 
  bool fPackedPixels; // GL_APPLE_packed_pixels or 1.2+
  bool fClientStorage; // GL_APPLE_client_storage
  bool fYCbCr; // GL_APPLE_ycbcr_422 (YUV texturing)
  bool fTextureRange; // GL_APPLE_texture_range (AGP texturing)
  bool fFence; // GL_APPLE_fence
  bool fVAR; // GL_APPLE_vertex_array_range
  bool fVAO; // GL_APPLE_vertex_array_object
  bool fElementArray; // GL_APPLE_element_array
  bool fVPEvals; // GL_APPLE_vertex_program_evaluators
  bool fFloatPixels; // GL_APPLE_float_pixels
  bool fFlushRenderer; // GL_APPLE_flush_render
  bool fPixelBuffer; // GL_APPLE_pixel_buffer
  bool fImaging; // GL_ARB_imaging  (not required in 1.2+)
  bool fTransposeMatrix; // GL_ARB_transpose_matrix or 1.3+
  bool fMultitexture; // GL_ARB_multitexture or 1.3+
  bool fTexEnvAdd; // GL_ARB_texture_env_add, GL_EXT_texture_env_add or 1.3+
  bool fTexEnvCombine; // GL_ARB_texture_env_combine or 1.3+
  bool fTexEnvDot3; // GL_ARB_texture_env_dot3 or 1.3+
  bool fTexEnvCrossbar; // GL_ARB_texture_env_crossbar or 1.4+
  bool fTexCubeMap; // GL_ARB_texture_cube_map or 1.3+
  bool fTexCompress; // GL_ARB_texture_compression or 1.3+
  bool fMultisample; // GL_ARB_multisample or 1.3+ (Anti-aliasing)
  bool fTexBorderClamp; // GL_ARB_texture_border_clamp or 1.3+
  bool fPointParam; // GL_ARB_point_parameters or 1.4+
  bool fVertexProg; // GL_ARB_vertex_program
  bool fFragmentProg; // GL_ARB_fragment_program
  bool fTexMirrorRepeat; // GL_ARB_texture_mirrored_repeat or 1.4+
  bool fDepthTex; // GL_ARB_depth_texture or 1.4+
  bool fShadow; // GL_ARB_shadow or 1.4+
  bool fShadowAmbient; // GL_ARB_shadow_ambient
  bool fVertexBlend; // GL_ARB_vertex_blend
  bool fWindowPos; // GL_ARB_window_pos or 1.4+
  bool fTex3D; // GL_EXT_texture3D or 1.2+
  bool fClipVolHint; // GL_EXT_clip_volume_hint
  bool fRescaleNorm; // GL_EXT_rescale_normal or 1.2+
  bool fBlendColor; // GL_EXT_blend_color or GL_ARB_imaging
  bool fBlendMinMax; // GL_EXT_blend_minmax or GL_ARB_imaging
  bool fBlendSub; // GL_EXT_blend_subtract or GL_ARB_imaging
  bool fCVA; // GL_EXT_compiled_vertex_array
  bool fTexLODBias; // GL_EXT_texture_lod_bias or 1.4+
  bool fABGR; // GL_EXT_abgr
  bool fBGRA; // GL_EXT_bgra or 1.2+
  bool fTexFilterAniso; // GL_EXT_texture_filter_anisotropic
  bool fPaletteTex; // GL_EXT_paletted_texture
  bool fShareTexPalette; // GL_EXT_shared_texture_palette
  bool fSecColor; // GL_EXT_secondary_color or 1.4+
  bool fTexCompressS3TC; // GL_EXT_texture_compression_s3tc
  bool fTexRect; // GL_EXT_texture_rectangle
  bool fFogCoord; // GL_EXT_fog_coord
  bool fDrawRangeElements; // GL_EXT_draw_range_elements
  bool fStencilWrap; // GL_EXT_stencil_wrap or 1.4+
  bool fBlendFuncSep; // GL_EXT_blend_func_separate or 1.4+
  bool fMultiDrawArrays; // GL_EXT_multi_draw_arrays or 1.4+
  bool fShadowFunc; // GL_EXT_shadow_funcs
  bool fStencil2Side; // GL_EXT_stencil_two_side
  bool fColorSubtable; // GL_EXT_color_subtable or GL_ARB_imaging
  bool fConvolution; // GL_EXT_convolution or GL_ARB_imaging
  bool fHistogram; // GL_EXT_histogram or GL_ARB_imaging
  bool fColorTable; // GL_SGI_color_table or GL_ARB_imaging
  bool fColorMatrix; // GL_SGI_color_matrix
  bool fTexEdgeClamp; // GL_SGIS_texture_edge_clamp or 1.2+
  bool fGenMipmap; // GL_SGIS_generate_mipmap or 1.4+
  bool fTexLOD; // GL_SGIS_texture_lod or 1.2+
  bool fPointCull; // GL_ATI_point_cull_mode
  bool fTexMirrorOnce; // GL_ATI_texture_mirror_once
  bool fPNtriangles; // GL_ATI_pn_triangles or GL_ATIX_pn_triangles
  bool fTextFragShader; // GL_ATI_text_fragment_shader
  bool fBlendEqSep; // GL_ATI_blend_equation_separate
  bool fBlendWeightMinMax; // GL_ATI_blend_weighted_minmax
  bool fCombine3; // GL_ATI_texture_env_combine3
  bool fSepStencil; // GL_ATI_separate_stencil
  bool fArrayRevComps4Byte; // GL_ATI_array_rev_comps_in_4_bytes
  bool fPointSprite; // GL_NV_point_sprite
  bool fRegCombiners; // GL_NV_register_combiners
  bool fRegCombiners2; // GL_NV_register_combiners2
  bool fTexEnvCombine4; // GL_NV_texture_env_combine4
  bool fBlendSquare; // GL_NV_blend_square or 1.4+
  bool fFogDist; // GL_NV_fog_distance
  bool fMultisampleFilterHint; // GL_NV_multisample_filter_hint
  bool fTexGenReflect; // GL_NV_texgen_reflection
  bool fTexShader; // GL_NV_texture_shader
  bool fTexShader2; // GL_NV_texture_shader2
  bool fTexShader3; // GL_NV_texture_shader3
  bool fDepthClamp; // GL_NV_depth_clamp
  bool fLightMaxExp; // GL_NV_light_max_exponent
  bool fConvBorderModes; // GL_HP_convolution_border_modes or GL_ARB_imaging
  bool fRasterPosClip; // GL_IBM_rasterpos_clip
} GLCaps;

// this does a reasonable check to see if things have changed without being 
// too heavy weight; returns 1 if changed 0 if not
// checks num displays, displayID, displayMask, each display geometry and 
// renderer VRAM and ID
unsigned char HaveOpenGLCapsChanged (GLCaps aDisplayCaps[], 
                                     CGDisplayCount dspyCnt);


// This will walk all active displays and gather information about their
// hardware renderer 

// An array length (maxDisplays) and array of GLCaps are passed in. Up to
// maxDisplays of the array are filled in with the displays meeting the
// specified criteria.  The actual number of displays filled in is returned
// in dspyCnt.  Calling this function with maxDisplays of 0 will just
// return the number of displays in dspyCnt.

// Developers should note this is NOT an exhaustive list of all the
// capabilities one could query, nor a required set of capabilities,
// feel free to add or subtract queries as you find helpful for your 
// application/use.

// one note on mirrored displays... if the display configuration is 
// changed it is possible (and likely) that the current active display
// in a mirrored configuration (as identified by the OpenGL Display Mask)
// will change if the mirrored display is removed.  
// This is due to the preference of selection the external display as 
// the active display.  This may affect full screen apps which should 
// always detect display configuration changes and respond accordingly.

void CheckOpenGLCaps (CGDisplayCount maxDisplays, 
                      GLCaps * aDisplayCaps, 
                      CGDisplayCount * dspyCnt);